package fr.inria.arles.temperatureManagement.communication;

import fr.inria.arles.temperatureManagement.exceptions.MalformedQueryException;
import fr.inria.arles.temperatureManagement.exceptions.QueryException;
import org.cybergarage.upnp.Action;
import org.cybergarage.upnp.Device;
import static fr.inria.arles.temperatureManagement.utility.Utility.*;
import static fr.inria.arles.temperatureManagement.Constants.*;

/**
 * Provides communication with the Query Processsor UPnP Device.
 * @author ajay chhatwal
 */
public class QueryProcessorCommunicator {

    /**
     * Gets the user's current reference temperature setting.
     *
     * @param queryProcessor
     *            The Query Processor UPnP device
     *            changed
     * @param ID
     *            The unique identifier for the user whose settings are being
     *            changed
     * @return the Reference Temperature Setting of the user
     * @throws MalformedQueryException
     *             if there is an error in the syntax of the query.
     * @throws QueryException
     *             if there is an error in performing the desired action at the
     *             Query Processor Device
     */
    public static String getTemp(Device queryProcessor, String ID)
            throws MalformedQueryException,QueryException {

        System.out.println("Connecting to Query Processor Device :- "
                + QUERY_PROCESSOR_DEVICE
                + " to get temperature setting");
        Action action = queryProcessor.getAction(EXECUTE_QUERY_ACTION);
        String req = encode("GetTempQuery", ID);
        action.setArgumentValue(REQUEST_ARG, req);
        if (action.postControlAction()) {
            String res = action.getArgument(RESPONSE_ARG).getValue();
            String[] response = decode(res);
            if (response.length == 2 && response[0].equals("true")) {
                return response[1];
            } else {
                throw new MalformedQueryException();
            }
        } else {
            throw new QueryException();
        }
    }
       

    /**
     * Updates the user's current reference temperature setting by invoking the 
     * Query Processor.
     *
     * @param queryProcessor
     *            The Query Processor UPnP device
     * @param ID
     *            The unique identifier for the user whose settings are being
     *            changed
     * @param temp
     *            the reference temperature
     * @param partition
     *            The partition being referred to
     * @throws MalformedQueryException
     *             if there is an error in the syntax of the query
     * @throws QueryException
     *             if there is an error in performing the desired action at the
     *             Query Processor Device
     */

    public static void setTemp(Device queryProcessor,
            String ID, String partition, String temp)
            throws MalformedQueryException,QueryException {
        System.out.println("Connecting to Query Processor Device :- "
                + QUERY_PROCESSOR_DEVICE
                + " to update temperature setting");
        Action action = queryProcessor.getAction(EXECUTE_QUERY_ACTION);
        String req = encode("UpdateTempQuery", temp, ID);
        action.setArgumentValue(REQUEST_ARG, req);
        if (action.postControlAction()) {
            String res = action.getArgument(RESPONSE_ARG).getValue();
            String[] response = decode(res);
            if (!(response.length == 1 && response[0].equals("true"))) {
                throw new MalformedQueryException();
            }
        } else {
            throw new QueryException();
        }
    }

    /**
     * Authenticates a user on the basis of username,password and partition.
     *
     * @param queryProcessor
     *            The Query Processor UPnP device
     * @param username
     *            The username of the user
     * @param password
     *            The password of the user
     * @param partition
     *            The partition of the user
     * @return The unique identifier for the user
     * @throws MalformedQueryException
     *             if there is an error in the syntax of the query.
     * @throws QueryException
     *             if there is an error in performing the desired action at the
     *             Query Processor Device
     */
    public static String authenticate(Device queryProcessor,
            String username, String password, String partition)
            throws QueryException {
        System.out.println("Connecting to Query Processor Device :- "
                + QUERY_PROCESSOR_DEVICE
                + " to get authenticate user.");
        Action action = queryProcessor.getAction(EXECUTE_QUERY_ACTION);
        String req = encode("AuthenQuery", username, password,
                partition);
        action.setArgumentValue(REQUEST_ARG, req);
        if (action.postControlAction()) {
            String res = action.getArgument(RESPONSE_ARG).getValue();
            String[] response = decode(res);
            if (response.length == 2 && response[0].equals("true")) {
                return response[1];
            } else {
                throw new MalformedQueryException();
            }
        } else {
            throw new QueryException();
        }
    }

    /**
     * Authenticates a user on the basis of his/her RFID tag and also returns
     * his/her reference temperature setting.
     *
     * @param queryProcessor
     *            The Query Processor UPnP device
     * @param RFID
     *            The RFID tag of the user's RFID Card
     * @param partition
     *            The partition of the user
     * @return the Reference Temperature and the unique ID of the user
     * @throws MalformedQueryException
     *             if there is an error in the syntax of the query.
     * @throws QueryException
     *             if there is an error in performing the desired action at the
     *             Query Processor Device
     */
    public static String[] processRFID(Device queryProcessor, String RFID,
            String partition)
            throws QueryException {
        System.out.println("Connecting to Query Processor Device :- "
                + QUERY_PROCESSOR_DEVICE
                + " to process RFID request.");
        Action action = queryProcessor.getAction(EXECUTE_QUERY_ACTION);
        String req = encode("RFIDQuery", RFID, partition);
        action.setArgumentValue(REQUEST_ARG, req);
        if (action.postControlAction()) {
            String res = action.getArgument(RESPONSE_ARG).getValue();
            String[] response = decode(res);
            if (response.length == 3 && response[0].equals("true")) {
                return new String[]{response[1], response[2]};
            } else {
                throw new MalformedQueryException();
            }
        } else {
            throw new QueryException();
        }
    }
}
